/*
 * Copyright (c) 2021 Huawei Device Co., Ltd.
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
import {BreakpointInfo} from '../../breakpoint/BreakpointInfo'
import {BlockInfo} from '../../breakpoint/BlockInfo'
import {DownloadTask} from '../../DownloadTask'
import {EndCause} from '../../cause/EndCause'

export class Listener4Assist {
  callback: Listener4Callback;
  private assistExtend: AssistExtend;
  private info: BreakpointInfo;

  public setCallback(callback: Listener4Callback): void {
    this.callback = callback;
  }

  public setAssistExtend(assistExtend: AssistExtend): void {
    this.assistExtend = assistExtend;
  }

  public getAssistExtend(): AssistExtend {
    return this.assistExtend;
  }

  public infoReady(task: DownloadTask, info: BreakpointInfo, fromBreakpoint: boolean): void {
    this.info = info;

    if (this.assistExtend != null && this.assistExtend
      .dispatchInfoReady(task, info, fromBreakpoint)) {
      return;
    }

    if (this.callback != null) this.callback.infoReady(task, info, fromBreakpoint);
  }

  public fetchProgress(task: DownloadTask, blockIndex: number, currentReceivedSize: number): void {

    if (this.assistExtend != null
    && this.assistExtend.dispatchFetchProgress(task, blockIndex, currentReceivedSize)) {
      return;
    }

    if (this.callback != null) {
      this.callback.progressBlock(task, blockIndex, currentReceivedSize);
      this.callback.progress(task, currentReceivedSize);
    }
  }

  public fetchEnd(task: DownloadTask, blockIndex: number): void {

    if (this.assistExtend != null
    && this.assistExtend.dispatchBlockEnd(task, blockIndex)) {
      return;
    }

    if (this.callback != null) {
      this.callback.blockEnd(task, blockIndex, this.info.getBlock(blockIndex));
    }
  }

  public taskEnd(task: DownloadTask, cause: EndCause, realCause: Error): void {
    if (this.assistExtend != null
    && this.assistExtend.dispatchTaskEnd(task, cause, realCause)) {
      return;
    }

    if (this.callback != null) this.callback.taskEnd(task, cause, realCause);
  }
}

export interface AssistExtend {
  dispatchInfoReady(task: DownloadTask, info: BreakpointInfo, fromBreakpoint: boolean): boolean;

  dispatchFetchProgress(task: DownloadTask, blockIndex: number, increaseBytes: number): boolean;

  dispatchBlockEnd(task: DownloadTask, blockIndex: number): boolean;

  dispatchTaskEnd(task: DownloadTask, cause: EndCause, realCause: Error): boolean;
}

export interface Listener4Callback {

  infoReady(task: DownloadTask, info: BreakpointInfo, fromBreakpoint: boolean): void;

  progressBlock(task: DownloadTask, blockIndex: number, currentReceivedSize: number): void;

  progress(task: DownloadTask, currentReceivedSize: number): void;

  blockEnd(task: DownloadTask, blockIndex: number, info: BlockInfo): void;

  taskEnd(task: DownloadTask, cause: EndCause, realCause: Error): void;
}